package sms

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	redis2 "gitee.com/dsler-go/utils/servers/redis"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
	"math/rand"
	"strconv"
	"time"
	"unicode/utf8"
)

type SmsData struct {
	TemplateParam string `json:"template_param"`
	PhoneNumbers  string `json:"phone_numbers"`
	Key           string `json:"key"`
}

type CacheCode struct {
	Code   string `json:"code"`
	Mobile string `json:"mobile"`
}

var (
	client        *dysmsapi.Client
	ch            chan *SmsData
	sign_name     string
	template_code string
)

var (
	SMS_SIGN_IN_SECOND = 300 * time.Second
	SMS_MOBILE_PRE     = "dsl-xxx:api:m06ACD5nBYvcD6vi_sign_in_mobile_"
)

const SMS_KEY_RAND_LENGTH = 16

func Init(regionId, accessKyeId, accessSecret, signName, templateCode string, chanSize, nums, expireTime int, mobilePre string) (err error) {
	client, err = dysmsapi.NewClientWithAccessKey(regionId, accessKyeId, accessSecret)
	ch = make(chan *SmsData, chanSize)
	for i := 0; i < nums; i++ {
		go sendSms()
	}
	sign_name = signName
	template_code = templateCode
	SMS_SIGN_IN_SECOND = time.Duration(expireTime) * time.Second
	SMS_MOBILE_PRE = mobilePre
	return
}

func sendSms() {
	for {
		select {
		case msg := <-ch:
			// 生成六位数的验证码
			code := generateRangeNum(100000, 999999)
			aliSendSms(msg, code)
		default:
			time.Sleep(time.Second)
		}
	}
}

func aliSendSms(msg *SmsData, code string) {
	request := dysmsapi.CreateSendSmsRequest()
	request.Scheme = "https"
	request.PhoneNumbers = msg.PhoneNumbers
	request.SignName = sign_name
	request.TemplateCode = template_code
	request.TemplateParam = fmt.Sprintf("{\"code\":%s}", code)
	response, err := client.SendSms(request)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	//  &dysmsapi.SendSmsResponse{BaseResponse:(*responses.BaseResponse)(0xc00004ecc0), RequestId:"B221D9E7-3DD3-40B9-A7EA-8DD1621C815C", BizId:"876614788237204929^0", Code:"OK", Message:"OK"}
	//fmt.Printf("response is %#v\n", response)
	if response.Code == "OK" {
		// 发送成功后缓存验证码到redis
		cacheVal := &CacheCode{Code: code, Mobile: msg.PhoneNumbers}
		jsonStr, jErr := json.Marshal(cacheVal)
		if jErr != nil {
			fmt.Println("MapToJson err: ", jErr)
		}
		err = redis2.DefaultRedisV8.Client.Set(context.Background(), msg.Key, string(jsonStr), SMS_SIGN_IN_SECOND).Err()
		if err != nil {
			fmt.Println("验证码缓存失败：", err)
			return
		}
		err = redis2.DefaultRedisV8.Client.Set(context.Background(), SMS_MOBILE_PRE+msg.PhoneNumbers, msg.Key, SMS_SIGN_IN_SECOND).Err()
		if err != nil {
			fmt.Println("手机号登录KEY缓存失败：", err)
			return
		}
	}
}

func SendToChan(msg *SmsData) {
	ch <- msg
}

func generateRangeNum(min, max int) string {
	rand.Seed(time.Now().Unix())
	randNum := rand.Intn(max - min)
	randNum = randNum + min
	return strconv.Itoa(randNum)
}

// VerifySmsCode 校验手机验证码
func VerifySmsCode(key, code string) (string, error) {
	if key == "" || utf8.RuneCountInString(code) != 6 {
		return "", errors.New("无效的验证码")
	}

	cacheCode, err := redis2.DefaultRedisV8.Client.Get(context.Background(), key).Result()
	if err != nil {
		return "", err
	}

	var codeRes CacheCode
	err = json.Unmarshal([]byte(cacheCode), &codeRes)
	if err != nil {
		return "", errors.New("转码失败")
	}
	if codeRes.Code != code {
		return "", errors.New("验证码错误")
	}
	_ = redis2.DefaultRedisV8.Client.Del(context.Background(), key)
	_ = redis2.DefaultRedisV8.Client.Del(context.Background(), SMS_MOBILE_PRE+codeRes.Mobile)
	return codeRes.Mobile, nil
}
